package logging

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"time"

	"github.com/EDDYCJY/go-gin-example/pkg/file"
	"github.com/EDDYCJY/go-gin-example/pkg/setting"
)

type Level int

var (
	loggers      = make(map[string]*logInstance) // 修改为存储logInstance
	loggersLock  sync.Mutex
	currentDay   string // 记录当前日期
	dayCheckLock sync.Mutex
)

type logInstance struct {
	logger  *log.Logger
	file    *os.File
	lastDay string
	config  LoggerConfig
}

const (
	DEBUG Level = iota
	INFO
	WARNING
	ERROR
	FATAL
)

var levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}

// LoggerConfig 日志配置
type LoggerConfig struct {
	Name       string // 日志名称
	FilePath   string // 文件路径
	TimeFormat string // 时间格式
	FileExt    string // 文件扩展名
}

// init 初始化当前日期
func init() {
	currentDay = time.Now().Format("2006-01-02")
}

// checkDayChange 检查日期变化
func checkDayChange() bool {
	dayCheckLock.Lock()
	defer dayCheckLock.Unlock()

	today := time.Now().Format("2006-01-02")
	if today != currentDay {
		currentDay = today
		return true
	}
	return false
}

// GetLogger 获取或创建日志实例
func GetLogger(config LoggerConfig) *log.Logger {
	loggersLock.Lock()
	defer loggersLock.Unlock()

	// 检查日期变化，如果变化则关闭旧文件
	if checkDayChange() {
		for name, instance := range loggers {
			if instance.file != nil {
				instance.file.Close()
				delete(loggers, name)
			}
		}
	}

	// 检查是否已有实例
	if instance, exists := loggers[config.Name]; exists {
		return instance.logger
	}

	// 创建新日志实例
	filePath := config.FilePath
	if filePath == "" {
		filePath = getLogFilePath()
	}

	fileName := getDailyLogFileName(config)
	f, err := file.MustOpen(fileName, filePath)
	if err != nil {
		log.Fatalf("logging.Setup err: %v", err)
	}

	logger := log.New(f, "", log.LstdFlags)
	instance := &logInstance{
		logger:  logger,
		file:    f,
		lastDay: currentDay,
		config:  config,
	}
	loggers[config.Name] = instance

	return logger
}

// getDailyLogFileName 获取按天生成的日志文件名
func getDailyLogFileName(config LoggerConfig) string {
	today := time.Now().Format("2006-01-02")
	if config.Name != "" {
		return fmt.Sprintf("%s-%s.%s",
			config.Name,
			today,
			config.FileExt,
		)
	}
	return fmt.Sprintf("%s.%s",
		today,
		config.FileExt,
	)
}

// Log 通用日志方法
func Log(level Level, loggerName string, v ...interface{}) {
	config := LoggerConfig{
		Name:       loggerName,
		FilePath:   setting.AppSetting.RuntimeRootPath + setting.AppSetting.LogSavePath,
		TimeFormat: setting.AppSetting.TimeFormat,
		FileExt:    setting.AppSetting.LogFileExt,
	}

	logger := GetLogger(config)

	// 获取调用者信息
	_, file, line, ok := runtime.Caller(2)
	if !ok {
		file = "unknown"
		line = 0
	}

	// 简化文件路径
	shortFile := filepath.Base(file)

	prefix := fmt.Sprintf("[%s][%s:%d]", levelFlags[level], shortFile, line)
	logger.SetPrefix(prefix)
	logger.Println(v...)
}

// Debug 输出调试日志
func Debug(loggerName string, v ...interface{}) {
	Log(DEBUG, loggerName, v...)
}

// Info 输出信息日志
func Info(loggerName string, v ...interface{}) {
	Log(INFO, loggerName, v...)
}

// Warn 输出警告日志
func Warn(loggerName string, v ...interface{}) {
	Log(WARNING, loggerName, v...)
}

// Error 输出错误日志
func Error(loggerName string, v ...interface{}) {
	Log(ERROR, loggerName, v...)
}

// Fatal 输出致命错误日志
func Fatal(loggerName string, v ...interface{}) {
	Log(FATAL, loggerName, v...)
	os.Exit(1)
}
